package com.frank.loadinglibrary.utils;

import com.frank.loadinglibrary.common.BallBeatLoadComponent;
import com.frank.loadinglibrary.interfaces.OhosAnimatable;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.hiviewdfx.HiLog;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;

public abstract class Indicator<T extends Animator> implements OhosAnimatable {

    private ArrayList<T> mAnimators;

    private HashMap<T, AnimatorValue.ValueUpdateListener> mUpdateListeners = new HashMap<>();

    private boolean mHasAnimators;

    @Override
    public void start() {
        ensureAnimators();
        if (mAnimators == null) {
            return;
        }
        if (isRunning()) {
            return;
        }
        startAnimators();
    }


    @Override
    public void stop() {
        stopAnimators();
    }

    @Override
    public boolean isRunning() {
        if (mAnimators != null) {
            for (T animator : mAnimators) {
                return animator.isRunning();
            }
        }
        return false;
    }

    private void startAnimators() {
        for (int i = 0; i < mAnimators.size(); i++) {
            T animator = mAnimators.get(i);
            Class entityClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            if (entityClass.equals(AnimatorValue.class)) {
                AnimatorValue.ValueUpdateListener updateListener = mUpdateListeners.get(animator);
                if (updateListener != null) {
                    ((AnimatorValue) animator).setValueUpdateListener(updateListener);
                }
            } else {
                ((AnimatorGroup) animator).setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup start");
                    }

                    @Override
                    public void onStop(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup onStop");
                    }

                    @Override
                    public void onCancel(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup onCancel");
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup onEnd");
                    }

                    @Override
                    public void onPause(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup onPause");
                    }

                    @Override
                    public void onResume(Animator animator) {
                        HiLog.info(BallBeatLoadComponent.label, "AnimatorGroup onResume");
                    }
                });
            }

            animator.start();
        }
    }

    private void stopAnimators() {
        if (mAnimators != null) {
            for (T animator : mAnimators) {
                if (animator != null && animator.isRunning()) {
                    try {
                        animator.cancel();
                        animator.end();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private void ensureAnimators() {
        if (!mHasAnimators) {
            mAnimators = onCreateAnimators();
            mHasAnimators = true;
        }
    }

    public void addUpdateListener(T animator, AnimatorValue.ValueUpdateListener updateListener) {
        mUpdateListeners.put(animator, updateListener);
    }

    public abstract ArrayList<T> onCreateAnimators();

}
